package com.shanlitech.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import android.util.SparseArray;

import androidx.annotation.RequiresApi;

import com.shanlitech.lbs.types.RssiRecord;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class BluetoothScanner {
    public interface Listener {
        void onScan(List<RssiRecord> signals);
    }

    private static final String TAG = "SLBluetooth";

    private final Context mContext;
    private final BluetoothAdapter mBluetoothAdapter;
    private final List<RssiRecord> mRecords = new ArrayList<>();
    private boolean mStart = false;
    private Listener mListener;
    private long mReportPeriod = 100;
    private long mLastReport = 0;
    static final char[] hexArray = "0123456789ABCDEF".toCharArray();
    private final ScanCallback mCallback = new ScanCallback() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            final long now = System.currentTimeMillis();
            final ScanRecord sr = result.getScanRecord();

            //转化为16进制字符串
            bytes2HexString(sr.getBytes());

            final String name = sr.getDeviceName();
            if (name != null && !name.isEmpty()) {
                recordSignal(now, name, result.getRssi());
                report(now);
            }
        }

        public String bytes2HexString(byte[] bytes) {
            char[] hexChars = new char[bytes.length * 2];
            for (int j = 0; j < bytes.length; j++) {
                int v = bytes[j] & 0xFF;
                hexChars[j * 2] = hexArray[v >>> 4];
                hexChars[j * 2 + 1] = hexArray[v & 0x0F];
            }
            return new String(hexChars);

        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            Log.d(TAG, "onBatchScanResult " + results.size() + " record");
            super.onBatchScanResults(results);
            final long now = System.currentTimeMillis();
            for (ScanResult sr : results) {
                Log.i(TAG, "onScanResult: " + sr.getScanRecord().toString());
                final String name = sr.getScanRecord().getDeviceName();
                if (name != null && !name.isEmpty()) {
                    recordSignal(now, name, sr.getRssi());
                }
            }
            report(now);
        }

        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.i(TAG, "onScanFailed: ========" + errorCode);
        }
    };


    public BluetoothScanner(Context context) {
        mContext = context;
        final BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
    }

    public boolean isStart() {
        return mStart;
    }

    public boolean start(Listener listener, Set<String> nameFilters, int reportPeriod) {
        if (mStart) {
            return false;
        }
        if (!mBluetoothAdapter.isEnabled()) {
            return false;
        }
        mListener = listener;
        mReportPeriod = reportPeriod;
        mLastReport = System.currentTimeMillis();

        // setup filter
        final List<ScanFilter> filters = new ArrayList<>();
        for (String name : nameFilters) {
            filters.add(new ScanFilter.Builder().setDeviceName(name).build());
        }

        ScanSettings.Builder builder = new ScanSettings.Builder();

        // 设置扫描模式
        //      SCAN_MODE_LOW_LATENCY 扫描优先
        //      SCAN_MODE_LOW_POWER 省电优先
        //      SCAN_MODE_BALANCED 平衡模式
        //      SCAN_MODE_OPPORTUNISTIC 安卓6.0里面才用的模式
        builder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            builder.setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT);
            //信号比较强和扫描到的次数比较多才会报告
            // builder.setMatchMode(ScanSettings.MATCH_MODE_STICKY)
            //信号弱也会报告
            builder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
            builder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
        }
        builder.setReportDelay(0);

        final BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
//        scanner.startScan(filters, builder.build(), mCallback);
        scanner.startScan(mCallback);

        mStart = true;
        return true;
    }

    public void stop() {
        if (mStart) {
            Log.i(TAG, "Scanner stop");
            mStart = false;
            final BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
            scanner.stopScan(mCallback);
        }
    }

    private void report(long now) {
        if (mLastReport + mReportPeriod <= now) {
            if (!mRecords.isEmpty()) {
                mLastReport = now;
                mListener.onScan(mRecords);
                mRecords.clear();
            }
        }
    }

    private void recordSignal(long now, String name, int rssi) {
        RssiRecord record = new RssiRecord();
        record.timestamp = now;
        record.uuid = name;
        record.rssi = rssi;
        mRecords.add(record);
    }

}
